/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.inspur.edp.lcm.metadata.shell;

import com.inspur.edp.lcm.metadata.api.entity.MetadataProject;
import com.inspur.edp.lcm.metadata.api.entity.ProcessMode;
import com.inspur.edp.lcm.metadata.api.mvnEntity.MavenPackageRefs;
import com.inspur.edp.lcm.metadata.api.service.FileService;
import com.inspur.edp.lcm.metadata.api.service.MetadataProjectService;
import com.inspur.edp.lcm.metadata.core.MavenUtilsCore;
import com.inspur.edp.lcm.metadata.core.MetadataCoreManager;
import com.inspur.edp.lcm.metadata.core.MetadataProjectServiceImp;
import com.inspur.edp.lcm.metadata.core.PackageCoreService;
import com.inspur.edp.lcm.metadata.core.PackageGenerateCoreService;
import com.inspur.edp.lcm.metadata.devcommon.ManagerUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellOption;
import org.springframework.util.StringUtils;

/**
 * @author zhongchq
 */
@ShellComponent
public class MetadataCommand {
    private static final Logger log = LoggerFactory.getLogger(MetadataCommand.class);

    MetadataProjectService metadataProjectService = new MetadataProjectServiceImp();

    @Autowired
    FileService fileService;

    String gspprojectJson = "gspproject.json";
    String defaultVersion = "0.1.0-SNAPSHOT";
    String code = "code";

    @ShellMethod(key = "compile", value = "Compile Projects")
    public void compile(String path, String mavenPath) {
        path = path + File.separator + "java" + File.separator + "code";
        MavenUtilsCore mavenUtilsCore = new MavenUtilsCore();
        mavenUtilsCore.exeMavenCommand(path, mavenPath, "clean install");
    }

    //version为该工程的版本号。对于解析型，生成型默认的版本号为0.1.0-SNAPSHOT
    @ShellMethod(key = "push", value = "Push Metadata.")
    public void pushMetadata(String path, String repoId, String mavenPath,
        @ShellOption(defaultValue = "0.1.0-SNAPSHOT") String version) {
        ManagerUtils.setMavenStoragePath(mavenPath);
        final ProcessMode processMode = metadataProjectService.getProcessMode(path);
        PackageCoreService packageCoreService = new PackageCoreService();
        switch (processMode.toString()) {
            case "interpretation":
                packageCoreService.deployMdpkgForInterpretation(path, repoId, version, null, mavenPath);
                break;
            default:
                packageCoreService.deploySnapshotMdVersion(path, repoId, version, false, mavenPath);
        }
    }

    /***
     * @author zhongchq
     * @param path 工程路径
     **/
    @ShellMethod(key = "compileall", value = "Compile All Projects UnderDir")
    public void compileAllProjects(String path, String mavenPath) {
        List<String> allDirectories = new ArrayList<>();
        List<String> directories = fileService.getAllProjectsDirectories(path, allDirectories, gspprojectJson);
        MavenUtilsCore mavenUtilsCore = new MavenUtilsCore();
        for (String proDir : directories) {
            proDir = proDir + File.separator + "java" + File.separator + "code";
            mavenUtilsCore.exeMavenCommand(proDir, mavenPath, "clean install");
        }
    }

    @ShellMethod(key = "extract", value = "Extract Package.")
    public void extract(String path, String desDir) {
        List<String> allDirectories = new ArrayList<>();
        List<String> directories = fileService.getAllProjectsDirectories(path, allDirectories, gspprojectJson);
        for (String directory : directories) {
            String publishDir = directory + File.separator + "publish";
            if (new File(publishDir).exists()) {
                fileService.folderCopy(publishDir, desDir);
            }
        }
    }

    @ShellMethod(key = "restore", value = "Pull Metadata Package.")
    public void restore(String path, String mavenPath) {
        String packagePathT = Utils.createTempDir();
        try {
            PackageCoreService mdPkgService = new PackageCoreService();
            mdPkgService.restore(path, true, mavenPath, packagePathT);
            log.info("restore complete");
        } finally {
            log.info("clear temp files");
            Utils.delDir(packagePathT);
            log.info("clear complete");
        }
    }

    @ShellMethod(key = "restoreWithPath", value = "Pull Metadata Package with packagePath.")
    public void restore(String path, String mavenPath, String packagePath) {
        String packagePathT = "";
        if (StringUtils.isEmpty(packagePath)) {
            packagePathT = Utils.createTempDir();
        }
        try {
            PackageCoreService mdPkgService = new PackageCoreService();
            mdPkgService.restore(path, true, mavenPath, packagePathT);
        } finally {
            if (StringUtils.isEmpty(packagePath)) {
                Utils.delDir(packagePathT);
            }
        }
    }

//    @ShellMethod(key = "generatecode",value = "Generate Code.")
////    public void generateCode(String path) throws Exception {
////        generateService.generate(path);
////    }

    @ShellMethod(key = "packmd", value = "Generate Metadata Package.")
    public void generateMdPack(String path) {
        path = path + File.separator + "metadata";
//        ManagerUtils.setDevRootPath(devPath);
        PackageGenerateCoreService packageGenerateCoreService = new PackageGenerateCoreService();
        packageGenerateCoreService.generatePackage(path);
        log.info("元数据打包完成！");
    }

    /**
     * @param boPath bo工程所在路径，相对于projects.eg:bf/df
     * @throws IOException IO异常
     * @author zhongchq
     **/
    @ShellMethod("Update Api Modules Dependencies Version.")
    void updateApiDependencies(String boPath) throws IOException {
        File projDir = new File(boPath);
        List<String> allDirectories = new ArrayList<>();
        List<String> directories = fileService.getAllProjectsDirectories(boPath, allDirectories, gspprojectJson);
        for (String dir : directories) {
            File file = new File(dir);
            String mdprojPath = "metadata" + File.separator + file.getName() + ".mdproj";
            MetadataCoreManager manager = new MetadataCoreManager();
            MetadataProject metadataProjInfo = manager.getMetadataProjInfo(file.getPath() + File.separator + mdprojPath);
            List<MavenPackageRefs> refs = metadataProjInfo.getMavenPackageRefs();
            String apiPath = file.getPath() + "/java/code/api/pom.xml";
            if (!(refs == null)) {
                try (FileInputStream fis = new FileInputStream(apiPath)) {
                    MavenXpp3Reader reader = new MavenXpp3Reader();
                    Model model = reader.read(fis);
                    List<Dependency> dependencies = model.getDependencies();
                    dependencies.clear();
                    if (refs.size() > 0) {
                        for (MavenPackageRefs ref : refs) {
                            Dependency dependency = new Dependency();
                            dependency.setGroupId(ref.getGroupId());
                            dependency.setArtifactId(ref.getArtifactId());
                            if (ref.getVersion().startsWith("m")) {
                                dependency.setVersion(ref.getVersion().substring(1));
                            } else {
                                dependency.setVersion(ref.getVersion());
                            }
                            dependencies.add(dependency);
                        }
                    }
                    model.setDependencies(dependencies);
                    MavenXpp3Writer mavenXpp3Writer = new MavenXpp3Writer();
                    try (FileOutputStream fileOutputStream = new FileOutputStream(apiPath)) {
                        mavenXpp3Writer.write(fileOutputStream, model);
                    }
                } catch (IOException | XmlPullParserException e) {
                    throw new IOException("update apimodules error!", e);
                }
            }

        }
    }
}